package cbir;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;

import javax.imageio.ImageIO;
import net.semanticmetadata.lire.DocumentBuilder;
import net.semanticmetadata.lire.ImageDuplicates;
import net.semanticmetadata.lire.ImageSearchHits;
import net.semanticmetadata.lire.ImageSearcher;
import net.semanticmetadata.lire.ImageSearcherFactory;
import net.semanticmetadata.lire.impl.DocumentFactory;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;


public class Search {
	
	private String indexPath;
	
	public Search(String imgP, String indP) {
		this.indexPath = indP;
	}
	
	public LinkedList<Field> searchWeighted(String query, int maxHits, float colorHistogramWeight, float colorDistributionWeight, float textureWeight) throws CorruptIndexException, IOException{
//		System.out.println("\nsearchWeighted("+maxHits+","+colorHistogramWeight+","+colorDistributionWeight+","+textureWeight+")\n");
//		long start = System.currentTimeMillis();
		IndexReader reader = IndexReader.open(indexPath);
		ImageSearcher searcher = ImageSearcherFactory.createWeightedSearcher(maxHits, colorHistogramWeight, colorDistributionWeight, textureWeight);
		FileInputStream imageStream = new FileInputStream(query);
		BufferedImage bimg = ImageIO.read(imageStream);
		ImageSearchHits hits = null;
		hits = searcher.search(bimg, reader);
		int n = reader.numDocs();
		
//	 	PROVA AD USARLO SE VEDI CHE SCAZZA
//		start2 = System.currentTimeMillis();
//		hits = searcher.search(hits.doc(0), reader);
//		end2 = System.currentTimeMillis();
//		System.out.println("ricerca su document: "+ (end2 - start2));
		
		LinkedList<Field> ll = new LinkedList<Field>();
		Field campo = null;
		
		for (int i = 0; i < (maxHits > n ? n : maxHits); i++) {
			campo = new Field(hits.score(i), hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
			ll.add(campo);	
		} 
		
//		long end = System.currentTimeMillis();
//		System.out.println(end-start + " ms");
		
		return ll;
	}
		
	public LinkedList<Field> searchWeighted(String query, float colorHistogramWeight, float colorDistributionWeight, float textureWeight) throws CorruptIndexException, IOException{
//		System.out.println("\nsearchWeighted("+colorHistogramWeight+","+colorDistributionWeight+","+textureWeight+")\n");
//		long start = System.currentTimeMillis();
		
		IndexReader reader = IndexReader.open(indexPath);
		int n = reader.numDocs();
		
		ImageSearcher searcher = ImageSearcherFactory.createWeightedSearcher(n, colorHistogramWeight, colorDistributionWeight, textureWeight);
		
		FileInputStream imageStream = new FileInputStream(query);
		BufferedImage bimg = ImageIO.read(imageStream);
		
		ImageSearchHits hits = null;
		hits = searcher.search(bimg, reader);
		
// 	PROVA AD USARLO SE VEDI CHE SCAZZA
//		start2 = System.currentTimeMillis();
//		hits = searcher.search(hits.doc(0), reader);
//		end2 = System.currentTimeMillis();
//		System.out.println("ricerca su document: "+ (end2 - start2));

		LinkedList<Field> ll = new LinkedList<Field>();
		Field campo = null;

		
		for (int i = 0; i < n; i++) {
			campo = new Field(hits.score(i), hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
			ll.add(campo);	
		} 
		
//		long end = System.currentTimeMillis();
//		System.out.println(end-start + " ms");
		
		return ll;
	}
	
	/** Return: una lista ordinata di risultati */
	public LinkedList<Field> searchForColor(Color c) throws CorruptIndexException, IOException{
//		System.out.println("searchForColor("+c.toString()+")");
		
		IndexReader reader = IndexReader.open(indexPath);
		int n = reader.numDocs();
		ImageSearcher searcher = ImageSearcherFactory.createColorOnlySearcher(n);
		Document document = DocumentFactory.createColorOnlyDocument(c);
		ImageSearchHits hits = searcher.search(document, reader);	
		
		LinkedList<Field> ll = new LinkedList<Field>();
		Field campo;
		
		for (int i = 0; i < n; i++) {
			campo = new Field(hits.score(i), hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
			ll.add(campo);	
		}
		
		return ll;
	}
	
	/** Return: una lista ordinata di 'maxHits' risultati */
	public ArrayList<Img> searchForColor(int maxHits, Color c, String serverName, String contextPath) throws CorruptIndexException, IOException{
		IndexReader reader = IndexReader.open(indexPath);
		ImageSearcher searcher = ImageSearcherFactory.createColorOnlySearcher(maxHits);
		Document document = DocumentFactory.createColorOnlyDocument(c);
		
		
		ImageSearchHits hits = searcher.search(document, reader);
		int n = reader.numDocs();
		
		ArrayList<Img> ll = new ArrayList<Img>();
		Img campo;
		
		for (int i = 0; i < (maxHits > n ? n : maxHits); i++) {
			campo = new Img(hits.score(i), hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue(), serverName, contextPath);
			ll.add(campo);
		}
		
		return ll;
	}
	


	public LinkedList<Field> simpleSearch(String test, String testTh, int memorizzazione, int maxHits) throws CorruptIndexException, IOException{		
//		System.out.println("simpleSearch("+maxHits+", " + memorizzazione + " , " + maxHits + ")\n");
		
		IndexReader reader = IndexReader.open(indexPath);
		ImageSearcher searcher = ImageSearcherFactory.createSimpleSearcher(maxHits);
		
		// Leggo la immagine di test, la nostra query
		FileInputStream imageStream = new FileInputStream(test);
		
		BufferedImage bimg = ImageIO.read(imageStream);
		// Cerca immagini simili:
		ImageSearchHits hits = null;
		hits = searcher.search(bimg, reader);
		
//		for (int i = 0; i < maxHits; i++) {
//		System.out.println(hits.score(i) + "\t" + hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
//		}

//		GENERA IL DOCUMENTO DELL'IMMAGINE DI TEST
		Document document = hits.doc(0);

		// Cerca documenti simili in base alle caratteristiche del DocumentBuilder
		hits = searcher.search(document, reader);
		
//		LinkedList<String> ll = new LinkedList<String>();
		LinkedList<Field> ll = new LinkedList<Field>();
		Field campo;
		
		System.out.println("Score\t\tImg");
		for (int i = 0; i < maxHits; i++) {
//			System.out.println(hits.score(i) + "\t" + hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
			campo = new Field(hits.score(i), hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER).stringValue());
			ll.add(campo);	
		} 
		
		if(memorizzazione == 0)
			rimuoviTracce(test, testTh);
		
		return ll;
		
	}

	private void rimuoviTracce(String test, String testTh) {
		// TODO Auto-generated method stub
		System.out.println("Rimozione immagine di query...");
		
		// Cancello immagine
		File f = new File(test);
		if( f.delete() ){ 
			System.out.println("Cancellato " + f);			
		}else{ 	
			System.out.println("Impossibile cancellare " + f);
		} 
		
		// Cancello thumb
		f = new File(testTh);
		if( f.delete() ){ 
			System.out.println("Cancellato " + f);			
		}else{ 	
			System.out.println("Impossibile cancellare " + f);
		} 
		
	}

	public void findDuplicates() throws CorruptIndexException, IOException{
		IndexReader reader = IndexReader.open(indexPath); 
		ImageSearcher searcher = ImageSearcherFactory.createDefaultSearcher();
		ImageDuplicates dupl = searcher.findDuplicates(reader);
		if(dupl != null){
			for (int i=0; i< dupl.length(); i++) {
				System.out.println(dupl.getDuplicate(i).toString());
			}
		}
		
	}
}
